import os
import sqlite3
import logging
from datetime import datetime
from flask import Flask, render_template, request, redirect, url_for, session, jsonify
from flask_socketio import SocketIO, join_room, leave_room
from PIL import Image, ImageFont, ImageDraw
from openai import OpenAI

from config import MANAGER_PASSWORD, ANSWERS_SAVE_PATH, EGG_SERVER_URL
import threading
import time



client = OpenAI(
    # 若没有配置环境变量，请用百炼API Key将下行替换为：api_key="sk-xxx",
    api_key=os.getenv("DASHSCOPE_API_KEY"),
    # 如何获取API Key：https://help.aliyun.com/zh/model-studio/developer-reference/get-api-key
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

# 自定义日志过滤器
class RequestLogFilter(logging.Filter):
    def filter(self, record):
        # 过滤掉包含特定格式的日志
        if '/socket.io/?EIO=4&transport=polling&t' in record.getMessage():
            return False
        return True

# 获取 Werkzeug 日志记录器
werkzeug_logger = logging.getLogger('werkzeug')
# 添加自定义过滤器
werkzeug_logger.addFilter(RequestLogFilter())

# 配置日志
logging.basicConfig(
    level=logging.DEBUG,
    format='%(levelname)s-[%(threadName)s]-%(message)s',
    handlers=[
        logging.FileHandler('app.log'),
        logging.StreamHandler()
    ]
)

app = Flask(__name__, static_folder='static')
app.secret_key = os.urandom(24)
socketio = SocketIO(app)


# 初始化数据库
def init_db():
    conn = sqlite3.connect('app.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS users
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                 username TEXT NOT NULL UNIQUE,
                 password TEXT NOT NULL,
                 is_manager BOOLEAN NOT NULL DEFAULT 0)''')
    c.execute('''CREATE TABLE IF NOT EXISTS assessments
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                 user_id INTEGER NOT NULL,
                 answers TEXT NOT NULL,
                 blood_pressure_high INTEGER,
                 blood_pressure_low INTEGER,
                 heart_rate INTEGER,
                 date TEXT NOT NULL,
                 deepseek_result TEXT,
                 FOREIGN KEY (user_id) REFERENCES users(id))''')
    c.execute('''CREATE TABLE IF NOT EXISTS experiences
                 (id INTEGER PRIMARY KEY AUTOINCREMENT,
                 user_id INTEGER NOT NULL,
                 date TEXT NOT NULL,
                 image_path TEXT NOT NULL,
                 FOREIGN KEY (user_id) REFERENCES users(id))''')
    conn.commit()
    conn.close()
init_db()


# 请求钩子，在每个请求处理之前执行
@app.before_request
def log_request_info():
    login_ip = request.remote_addr
    # 从 session 中获取用户信息
    # logging.info(f"Request IP: {session.values()}")


# 注册页面
@app.route('/register', methods=['GET', 'POST'])
def register():
    error = None
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        is_manager = request.form.get('is_manager') == 'on'
        if is_manager and password != MANAGER_PASSWORD:
            error = "管理员密码错误，请重新输入。"
        else:
            conn = sqlite3.connect('app.db')
            c = conn.cursor()
            try:
                c.execute("INSERT INTO users (username, password, is_manager) VALUES (?,?,?)",
                          (username, password, is_manager))
                conn.commit()
                return redirect(url_for('login'))
            except sqlite3.IntegrityError:
                error = "用户名已存在，请选择其他用户名。"
            finally:
                conn.close()
    return render_template('register.html', error=error)


# 登录页面
@app.route('/', methods=['GET', 'POST'])
@app.route('/login', methods=['GET', 'POST'])
def login():
    error = None
    if request.method == 'POST':
        username = request.form.get('username')
        password = request.form.get('password')
        conn = sqlite3.connect('app.db')
        c = conn.cursor()
        c.execute("SELECT id, is_manager FROM users WHERE username =? AND password =?", (username, password))
        user = c.fetchone()
        conn.close()
        if user:
            session['user_id'] = user[0]
            session['is_manager'] = user[1]
            session['username'] = username

            if session['is_manager']:
                return redirect(url_for('manager'))

            # 检查用户是否填写过测评题
            conn = sqlite3.connect('app.db')
            c = conn.cursor()
            c.execute("SELECT * FROM assessments WHERE user_id =?", (session['user_id'],))
            assessment = c.fetchone()
            conn.close()
            if assessment:
                return redirect(url_for('submit_success'))
            else:
                return redirect(url_for('assessment'))
        else:
            error = "用户名或密码错误，请重新输入。"
    return render_template('login.html', error=error)


# 注销功能
@app.route('/logout')
def logout():
    session.pop('user_id', None)
    session.pop('is_manager', None)
    session.pop('username', None)
    return redirect(url_for('login'))


# 测评页面
@app.route('/assessment', methods=['GET', 'POST'])
def assessment():
    if 'user_id' not in session:
        return redirect(url_for('login'))

    questions = [
        "我觉得很难让自己安静下来",
        "我感到口干舌燥",
        "我好像一点都没有感觉到任何愉快、舒畅",
        "我感到呼吸困难(例如:气喘或透不过气来)",
        "我感到很难主动去开始工作",
        "我对事情往往做出过敏反应",
        "我感到颤抖(例如，手抖)",
        "我觉得自己消耗了很多精力",
        "我担心一些可能让自己恐慌或出丑的场合",
        "我觉得自己对不久的将来没有什麼可期盼的",
        "我感到忐忑不安",
        "我感到很难放松自己",
        "我感到忧郁沮丧",
        "我无法容忍任何阻碍我继续工作的事情",
        "我感到快要崩溃了",
        "我对任何事情都不能产生热情",
        "我觉得自己不怎麽配做人",
        "我发觉自己很容易被触怒",
        "即使在没有明显的体力活动时，我也感到心律不正常",
        "我无缘无故地感到害怕",
        "我感到生命毫无意义"
    ]
    if request.method == 'POST':
        answers = []
        for i in range(1, 22):
            answer = request.form.get(f'q{i}')
            answers.append(questions[i - 1])
            answers.append(answer)
        answers_str = ','.join(answers)
        blood_pressure_high = request.form.get('blood_pressure_high')
        blood_pressure_low = request.form.get('blood_pressure_low')
        heart_rate = request.form.get('heart_rate')
        answers.append("血压（高压）：")
        answers.append(blood_pressure_high)
        answers.append("血压（低压）：")
        answers.append(blood_pressure_low)
        answers.append("心率：")
        answers.append(heart_rate)


        date = datetime.now().strftime("%Y-%m-%d_%H:%M:%S")
        conn = sqlite3.connect('app.db')
        c = conn.cursor()
        c.execute(
            "INSERT INTO assessments (user_id, answers, blood_pressure_high, blood_pressure_low, heart_rate, date) VALUES (?,?,?,?,?,?)",
            (session['user_id'], answers_str, blood_pressure_high, blood_pressure_low, heart_rate, date))
        conn.commit()
        conn.close()

        saveAnswer2File(answers)

        # 发送用户ID到另一个服务器
        try:
            response = request.post(
                EGG_SERVER_URL,
                json={'user_id': session['user_id']},
                timeout=5
            )
            response.raise_for_status()
            logging.info(f"成功发送用户ID到远程服务器: {session['user_id']}")
        except request.exceptions.RequestException as e:
            logging.error(f"发送用户ID到远程服务器失败: {str(e)}")

        return redirect(url_for('submit_success'))
    return render_template('assessment.html', questions=questions)

@app.route('/submit_success')
def submit_success():
    return render_template('submit_success.html')

def saveAnswer2File(answers):
    # 创建保存目录
    save_dir = os.path.join(ANSWERS_SAVE_PATH, str(session['user_id']),"AssessmentAndAnswer")
    os.makedirs(save_dir, exist_ok=True)
    # 生成带时间戳的文件名
    timestamp = datetime.now().strftime("%Y%m%d_%H%M%S")
    filename = str(session['user_id']) + f"_answers_{timestamp}.txt"
    file_path = os.path.join(save_dir, filename)
    # 写入文件内容

    # 添加日志记录
    logging.info(f"正在保存用户 {session['user_id']} 的答案到目录: {save_dir}")

    try:
        with open(file_path, 'w', encoding='utf-8') as f:
            f.write(str(answers))
        logging.info(f"成功生成评估报告: {filename}")

    except Exception as e:
        logging.error(f"保存评估报告失败: {str(e)}")
        raise

    return file_path


# 调用 DeepSeek 进行评估
def call_deepseek(assessment_id, answers, user_id):
    # 这里需要替换为实际的 DeepSeek API 请求
    # 示例代码，模拟请求
    # time.sleep(5)  # 模拟请求耗时
    # 记录请求开始时间
    logging.info(f"request big model begin... ")
    start_time = time.time()
    strAnswer = '输出最多300字左右建议:'.join(answers)
    completion = client.chat.completions.create(
        # model="deepseek-r1",  # 此处以 deepseek-r1 为例，可按需更换模型名称。
        model="deepseek-v3",  # 此处以 deepseek-r1 为例，可按需更换模型名称。
        # model="qwen-plus",  # 模型列表：https://help.aliyun.com/zh/model-studio/getting-started/models
        messages=[
            {'role': 'user', 'content': strAnswer}
        ])

    result = completion.choices[0].message.content
    # 记录请求结束时间，并计算本次耗时
    end_time = time.time()
    elapsed_time = end_time - start_time
    logging.info(f"本次请求大模型时长（秒）: {elapsed_time} ")

    conn = sqlite3.connect('app.db')
    c = conn.cursor()
    c.execute("UPDATE assessments SET deepseek_result =? WHERE id =?", (result, assessment_id))
    conn.commit()
    conn.close()

    # 通过 WebSocket 通知前端更新结果
    socketio.emit('update_report', {'result': result}, room=user_id)


# 报告页面
@app.route('/report', methods=['GET', 'POST'])
def report():
    if 'user_id' not in session:
        return redirect(url_for('login'))
    conn = sqlite3.connect('app.db')
    c = conn.cursor()
    # 获取最后一次测评结果
    c.execute("SELECT * FROM assessments WHERE user_id =? ORDER BY date DESC LIMIT 1", (session['user_id'],))
    assessment = c.fetchone()
    # 获取用户的脑电波实验图片（结果）
    c.execute("SELECT image_path FROM experiences WHERE user_id =? ORDER BY date DESC LIMIT 1", (session['user_id'],))
    experience = c.fetchone()
    conn.close()

    if assessment:
        answers = assessment[2].split(',')
        deepseek_result = assessment[7]  # 获取 DeepSeek 结果
        if not deepseek_result:
            # 首次进入，启动线程调用 DeepSeek
            assessment_id = assessment[0]
            thread = threading.Thread(target=call_deepseek, args=(assessment_id, answers, session['user_id']))
            thread.start()
            deepseek_result = "正在计算评估结果，请稍候..."
        else:
            pass  # 已有结果，直接使用

        # 简单示例分析结果
        analysis = "根据你的测评结果，整体情况较为复杂，可能在情绪和心理状态方面存在一些波动，建议你保持良好的生活习惯，适当进行运动和放松。同时，关注自己的情绪变化，如有需要，可以寻求专业帮助。"
        # return render_template('report.html', answers=answers, analysis=analysis,
        #                        image_path=experience[0] if experience else None, deepseek_result=deepseek_result)


        return render_template('report.html', analysis=analysis,
                               image_path=experience[0] if experience else None, deepseek_result=deepseek_result)
    else:
        return redirect(url_for('assessment'))


# 更新报告
@app.route('/update_report')
def update_report():
    if 'user_id' not in session:
        return redirect(url_for('login'))
    return redirect(url_for('report'))


# 再次测评
@app.route('/re_assessment')
def re_assessment():
    if 'user_id' not in session:
        return redirect(url_for('login'))
    # 清空该用户的测试数据
    user_id = session['user_id']
    conn = sqlite3.connect('app.db')
    c = conn.cursor()
    c.execute("DELETE FROM assessments WHERE user_id =?", (user_id,))
    conn.commit()
    conn.close()
    return redirect(url_for('assessment'))


# 管理页面
@app.route('/manager', methods=['GET', 'POST'])
def manager():
    if 'user_id' not in session or not session['is_manager']:
        return redirect(url_for('login'))

    music_dir = os.path.join(app.static_folder, 'music')
    try:
        music_files = sorted([f for f in os.listdir(music_dir) if f.endswith('.mp3') or f.endswith('.wav')])
    except FileNotFoundError:
        music_files = []

    return render_template('manager.html', music_files=music_files)



def beginExpriment(username):
    conn = sqlite3.connect('app.db')
    c = conn.cursor()
    c.execute("SELECT id FROM users WHERE username =?", (username,))
    user = c.fetchone()
    if user:
        user_id = user[0]
        import datetime
        date = datetime.datetime.now().strftime("%Y-%m-%d %H:%M:%S")
        project_root = os.path.dirname(os.path.abspath(__file__))

        # 生成图片
        img = Image.new('RGB', (200, 200), color=(73, 109, 137))
        d = ImageDraw.Draw(img)
        fnt = ImageFont.load_default()
        d.text((10, 10), f'User: {username}, Date: {date}', font=fnt, fill=(255, 255, 0))

        dateFormat = datetime.datetime.now().strftime("_%Y%m%d_%H%M%S.png")
        image_abs_path = os.path.join(project_root, 'static\\images', username + dateFormat)
        image_path = f'images/{username}{dateFormat}'
        img.save(f'static/{image_path}')
        # img.save(image_abs_path)
        # 保存到数据库
        c.execute("INSERT INTO experiences (user_id, date, image_path) VALUES (?,?,?)", (user_id, date, image_path))
        conn.commit()
    conn.close()


# WebSocket连接
@socketio.on('connect')
def handle_connect():
    sid = request.sid
    if 'user_id' in session:
        if 'online_users' not in session:
            session['online_users'] = []
        session['online_users'].append(sid)
        join_room(session['user_id'])
        logging.info(f"User {session['username']} (SID: {sid}) connected.")
    return 'Connected'

# WebSocket事件处理
@socketio.on('start_experiment')
def handle_start_experiment(data):
    username = data.get('username')
    app.logger.info(f"用户 {username} 开始实验")
    beginExpriment(username)

    socketio.emit('experiment_status', {'status': 'started'})
    return 'Experiment started'

@socketio.on('end_experiment')
def handle_end_experiment(data):
    username = data.get('username')
    app.logger.info(f"用户 {username} 结束实验")
    socketio.emit('experiment_status', {'status': 'ended'})
    return 'Experiment ended'


@socketio.on('disconnect')
def handle_disconnect():
    sid = request.sid
    if 'user_id' in session and 'online_users' in session:
        if sid in session['online_users']:
            session['online_users'].remove(sid)
        leave_room(session['user_id'])
        logging.info(f"User {session['username']} (SID: {sid}) disconnected.")


# 获取音乐文件列表接口
@app.route('/get_music_files')
def get_music_files():
    music_dir = os.path.join(app.static_folder, 'music')
    try:
        files = [f for f in os.listdir(music_dir) if f.endswith('.mp3')]
    except FileNotFoundError:
        files = []
    return jsonify(files)

@socketio.on('play_music')
def handle_play_music(data):
    filename = data.get('filename')
    user_id = session.get('user_id')
    logging.info(f"{datetime.now()}: UserId {user_id} play music {filename}");
    if user_id:
        # 向特定用户发送播放命令
        socketio.emit('start_playback', {'filename': filename}, room=user_id)

@socketio.on('pause_music')
def handle_pause_music():
    user_id = session.get('user_id')
    logging.info(f"{datetime.now()}: UserId {user_id} pause music");
    if user_id:
        # 向特定用户发送暂停命令
        socketio.emit('pause_playback', room=user_id)

@socketio.on('stop_music')
def handle_stop_music():
    user_id = session.get('user_id')
    logging.info(f"{datetime.now()}: UserId {user_id} stop music");
    if user_id:
        # 向特定用户发送停止命令
        socketio.emit('stop_playback', room=user_id)


if __name__ == '__main__':
    if not os.path.exists('static/images'):
        os.makedirs('static/images')
    socketio.run(app, host='0.0.0.0', port=9090, debug=True, allow_unsafe_werkzeug=True)
